VER="0.2.2"

import bluetooth
import binascii
import socket
import machine
import ntptime

# 配置 CPU 频率
CPU_FREQUENCY = 80000000
machine.freq(CPU_FREQUENCY)

SCAN_DURATION = 3000  # 扫描持续时间（毫秒）
SCAN_INTERVAL = 30000  # 扫描间隔（毫秒）
SCAN_WINDOW = 30000  # 扫描窗口（毫秒）
WAIT_TIME = 10  # 每次扫描后等待时间（秒）

log_list = []

    
def format_time(t):
    year, month, day, hour, minute, second, _, _ = t
    return "{:04d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}".format(year, month, day, hour, minute, second)


def add_log(log):
    global log_list
    current_time = format_time(time.localtime())
    log_with_time = f"[{current_time}] {log}"
    log_list.append(log_with_time)
    if len(log_list) > 30:
        log_list = log_list[-30:]


# 同步 NTP 时间并调整为时区为上海（UTC+8）
def sync_ntp_time():
    # 指定 NTP 服务器
    ntp_server = "ntp.aliyun.com"
    ntptime.host = ntp_server
    max_retries = 3
    retries = 0
    while retries < max_retries:
        try:
            ntptime.settime()
            # 获取当前的 UTC 时间元组
            utc_time = time.localtime()
            # 计算时间偏移量（东八区偏移 8 小时，单位为秒）
            offset = 8 * 3600
            # 调整为上海时间
            adjusted_time = time.localtime(time.mktime(utc_time) + offset)
            # 设置系统时间为调整后的上海时间
            machine.RTC().datetime((adjusted_time[0], adjusted_time[1], adjusted_time[2], 0, adjusted_time[3], adjusted_time[4], adjusted_time[5], 0))
            log = f"NTP 时间同步成功，已调整为上海时间，使用的 NTP 服务器: {ntp_server}"
            print(log)
            add_log(log)
            return True
        except Exception as e:
            retries += 1
            log = f"NTP 时间同步失败（第 {retries} 次尝试），使用的 NTP 服务器: {ntp_server}, 错误信息: {e}"
            print(log)
            add_log(log)
            time.sleep(2)
    log = f"NTP 时间同步失败，已达到最大重试次数，使用的 NTP 服务器: {ntp_server}"
    print(log)
    add_log(log)
    return False


# 定义蓝牙中断处理函数
last_adv_data = None


def bt_irq(event, data):
    global last_adv_data
    if event == 5:
        addr_type, addr, adv_type, rssi, adv_data = data
        mac_str = ':'.join('{:02x}'.format(x) for x in addr).upper()
        if mac_str == TARGET_MAC:
            try:
                ble.gap_scan(None)
                log = f"找到 MAC 地址为 {mac_str} 的设备"
                print(log)
                add_log(log)
                hex_adv_data = binascii.hexlify(adv_data).decode('utf-8')
                log = f"设备广播数据（十六进制）为: {hex_adv_data}"
                print(log)
                add_log(log)
                if hex_adv_data != last_adv_data:
                    send_data_to_server(mac_str, hex_adv_data)
                    last_adv_data = hex_adv_data
            except Exception as e:
                log = f"蓝牙数据处理出错: {e}"
                print(log)
                add_log(log)


# 发送数据到服务器
def send_data_to_server(mac, data):
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((SERVER_IP, SERVER_PORT))
        current_time = format_time(time.localtime())
        sta_if = network.WLAN(network.STA_IF)
        device_ip = sta_if.ifconfig()[0]  # 获取本设备的 IP 地址
        post_data = f"time={current_time}&mac={mac}&data={data}&ip={device_ip}"
        request = f"POST {SERVER_PATH} HTTP/1.1\r\n"
        request += f"Host: {SERVER_IP}:{SERVER_PORT}\r\n"
        request += "Content-Type: application/x-www-form-urlencoded\r\n"
        request += f"Content-Length: {len(post_data)}\r\n"
        request += "Connection: close\r\n\r\n"
        request += post_data

        s.sendall(request.encode())
        response = s.recv(1024)
        s.close()
        log = f"发送到服务器，内容: {post_data}"
        print(log)
        add_log(log)
    except Exception as e:
        current_time = format_time(time.localtime())
        log = f"在 {current_time} 发送数据时出错: {e}"
        print(log)
        add_log(log)


# Web 服务器处理函数
def handle_web_request(client):
    request = client.recv(1024)
    request = str(request)
    if "act=reboot" in request:
        response = """HTTP/1.1 200 OK
            Content-Type: text/html; charset=utf-8

            <!DOCTYPE html>
            <html>
            <head>
                <meta charset="UTF-8">
                <title>正在重启</title>
            </head>
            <body>
                <h2>设备正在重启，请稍候...</h2>
            </body>
            </html>"""
        client.sendall(response.encode())
        client.close()
        time.sleep(2)
        machine.reset()
    try:
        username_start = request.find("username=") + len("username=")
        username_end = request.find("&", username_start)
        username = request[username_start:username_end]

        password_start = request.find("password=") + len("password=")
        password_end = request.find(" HTTP", password_start)
        password = request[password_start:password_end]

        if username == WEB_USERNAME and password == WEB_PASSWORD:
            # 对日志列表进行反转
            reversed_log_list = log_list[::-1]
            log_html = "<br>".join(reversed_log_list)
            response = f"""HTTP/1.1 200 OK
                Content-Type: text/html; charset=utf-8

                <!DOCTYPE html>
                <html>
                <head>
                    <meta charset="UTF-8">
                    <title>运行日志</title>
                </head>
                <body>
                    <h2>运行日志 Ver {VER}</h2>
                    <p>{log_html}</p>
                    <a href="?act=reboot">重启设备</a>
                </body>
                </html>"""
        else:
            response = """HTTP/1.1 200 OK
                Content-Type: text/html; charset=utf-8

                <!DOCTYPE html>
                <html>
                <head>
                    <meta charset="UTF-8">
                    <title>登录失败</title>
                    <style>
                        body{background-color:#f4f4f4;display:flex;justify-content:center;align-items:center;height:100vh;margin:0}
                        form{background-color:#fff;padding:20px;border-radius:5px;box-shadow:0 0 10px rgba(0,0,0,0.1);width:350px}
                        label{display:block;margin-bottom:5px}
                        input[type="text"],input[type="password"]{width:95%;padding:8px;margin-bottom:15px;border:1px solid #ccc;border-radius:3px}
                        input[type="submit"]{background-color:#007BFF;color:#fff;padding:10px 15px;border:none;border-radius:3px;cursor:pointer}
                        input[type="submit"]:hover{background-color:#0056b3}
                    </style>
                </head>
                <body>
                    
                    <form method="post">
                        <h4>登录失败，请重试</h4>
                        <label for="username">用户:</label>
                        <input type="text" id="username" name="username"><br>
                        <label for="password">密码:</label>
                        <input type="password" id="password" name="password"><br>
                        <input type="submit" value="登录">
                    </form>
                </body>
                </html>"""
    except:
        response = """HTTP/1.1 200 OK
                Content-Type: text/html; charset=utf-8

                <!DOCTYPE html>
                <html>
                <head>
                    <meta charset="UTF-8">
                    <title>登录</title>
                    <style>
                        body{background-color:#f4f4f4;display:flex;justify-content:center;align-items:center;height:100vh;margin:0}
                        form{background-color:#fff;padding:20px;border-radius:5px;box-shadow:0 0 10px rgba(0,0,0,0.1);width:350px}
                        label{display:block;margin-bottom:5px}
                        input[type="text"],input[type="password"]{width:95%;padding:8px;margin-bottom:15px;border:1px solid #ccc;border-radius:3px}
                        input[type="submit"]{background-color:#007BFF;color:#fff;padding:10px 15px;border:none;border-radius:3px;cursor:pointer}
                        input[type="submit"]:hover{background-color:#0056b3}
                    </style>
                </head>
                <body>
                    
                    <form method="post">
                        <h4>请登录</h4>
                        <label for="username">用户:</label>
                        <input type="text" id="username" name="username"><br>
                        <label for="password">密码:</label>
                        <input type="password" id="password" name="password"><br>
                        <input type="submit" value="登录">
                    </form>
                </body>
                </html>"""
    client.sendall(response.encode())
    client.close()


# 启动 Web 服务器
def start_web_server():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('', 80))
    s.listen(5)
    while True:
        client, addr = s.accept()
        handle_web_request(client)


# 连接 Wi-Fi
if not do_connect():
    print("Wi-Fi 连接失败，程序退出")
else:
    # 同步 NTP 时间
    sync_ntp_time()
    # 创建蓝牙对象
    ble = bluetooth.BLE()
    ble.active(True)
    ble.irq(bt_irq)

    import _thread
    _thread.start_new_thread(start_web_server, ())

    while True:
        try:
            ble.gap_scan(SCAN_DURATION, SCAN_INTERVAL, SCAN_WINDOW)
            found = False
            start_time = time.ticks_ms()
            while time.ticks_diff(time.ticks_ms(), start_time) < SCAN_DURATION:
                pass
            if last_adv_data:
                log = "已找到目标设备，等待 10 秒后重新扫描..."
            else:
                log = "未找到目标设备，等待 10 秒后重新扫描..."
            print(log)
            add_log(log)
            time.sleep(WAIT_TIME)
        except KeyboardInterrupt:
            print("程序手动中断")
            break
        except Exception as e:
            print(f"扫描过程中出错: {e}")
            time.sleep(WAIT_TIME)
    


